/**
 * @file trasmitProcess.c
 * @brief 
 * @author xuesong (wenshaoliu@foxmail.com)
 * @version 1.0
 * @date 2023-06-21
 * 
 * @copyright Copyright (c) 2023  by xuesong
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-06-21     <td>1.0     <td>xuesong   <td>内容
 * </table>
 */
#include "trasmitProcess.h"
#include "osal.h"
#include "uartProtocol.h"
#include "user_prcess.h"
#include "bleuart_service.h"
#include "multi_role.h"
#include "pwrmgr.h"
#include "Xiaobai1248.h"
//-----------------------------------------------------------------
#ifndef     USER_TASK_START
#define     USER_TASK_START         0
#define     USER_TASK_STOP          1
#endif

#define     UART_SendBUF_SIZE       128
#define     UART_OneceBUF_SIZE      64
//-----------------------------------------------------------------
uint8_t         Trasmit_TaskID;
uint8_t         uart_send_buf[UART_OneceBUF_SIZE];
uint8_t         uart_send_buff[UART_SendBUF_SIZE];
#define         UartRxBufferSize 256
__align(4)      uint8_t pcUartRxBuf[UartRxBufferSize];
StreamBufferDef xStreamUartRx;
#define         UartTxBufferSize 1024
__align(4)      uint8_t pcUartTxBuf[UartTxBufferSize];
StreamBufferDef xStreamUartTx;
//-----------------------------------------------------------------
#define         SlaverRxBufferSize 1024
__align(4)      uint8_t pcSlaverRxBuf[SlaverRxBufferSize];
StreamBufferDef xStreamSlaverRx;
//--------------------------------
#define         SlaverTxBufferSize 1024
__align(4)      uint8_t pcSlaverTxBuf[SlaverTxBufferSize];
StreamBufferDef xStreamSlaverTx;
//-----------------------------------------------------------------
#define         MasterRxBufferSize 1024
__align(4)      uint8_t pcMasterRxBuf[MasterRxBufferSize];
StreamBufferDef xStreamMasterRx;
//--------------------------------
#define         MasterTxBufferSize 1024
__align(4)      uint8_t pcMasterTxBuf[MasterTxBufferSize];
StreamBufferDef xStreamMasterTx;
//-----------------------------------------------------------------
static void processMasterRcvData(void);
HuaweiCmdDef xBleCmdGet(uint8* buf, uint8 len);
//-----------------------------------------------------------------
void __ATTR_SECTION_SRAM__ uart_receive_callback(uart_Evt_t* pev)
{
    StreamStatusDef WriteResult = eSTREAM_NOT_ERR;
	switch(pev->type)
	{
		case UART_EVT_TYPE_RX_DATA:
		case UART_EVT_TYPE_RX_DATA_TO:
		{
// 			uint8_t i;
            
// 			for(i=0; i<pev->len; i++)
//             {
//                 if( (uartRxData.wr - uartRxData.rd) < UART_RX_BUF_INDEX )
//                 {
//                     uartRxData.data[(uartRxData.wr++)&UART_RX_BUF_INDEX] = pev->data[i];
//                 }
//                 else
//                 {
// //                    LOG("ble full\r\n");
//                     break;
//                 }
// 			}
            WriteResult = xStreamBufferWrite(&xStreamUartRx,pev->data,pev->len);
            if(UART_EVT_TYPE_RX_DATA_TO == pev->type || eSTREAM_SPACE_NOT_ENOUGH == WriteResult)
                Transmit_task_set(USER_TASK_START, TrasmitEvent_UART_RCV, 5);
		}
		break;
		
		case UART_EVT_TYPE_TX_COMPLETED:
//			LOG("tx completed\r\n");
            Transmit_task_set(USER_TASK_START, TrasmitEvent_UART_TX, NULL);
		break;
	}
}
//-----------------------------------------------------------------
void ble_data_rec_evt(ble_data_evt_t* pev)
{
    StreamStatusDef WriteResult = eSTREAM_NOT_ERR;
	switch(pev->ev){
        case BLE_EVT_TX_NOTI_DISABLED:
            
        break;
        
        case BLE_EVT_TX_NOTI_ENABLED:
            //LOG("BUP_OSAL_EVT_NOTIFY_DATA\n");
        break;
        
        case BLE_EVT_BLE_DATA_RECIEVED:
//            LOG("ble rec:");
            if(pev->role == ROLE_SLAVE)
            {
                WriteResult = xStreamBufferWrite(&xStreamSlaverRx,pev->data,pev->param);
                Transmit_task_set(USER_TASK_START, TrasmitEvent_Slaver_RCV, 5);
            }
            else
            {
                WriteResult = xStreamBufferWrite(&xStreamMasterRx,pev->data,pev->param);
                Transmit_task_set(USER_TASK_START, TrasmitEvent_Master_RCV, 5);
            }
//            LOG("\r\n");
        break;
        
        default:
        
        break;
	}
}
//-----------------------------------------------------------------
void TrasmitPrcess_Init(uint8 task_id)
{
    Trasmit_TaskID = task_id;
    xStreamBufferStaticCreate(&xStreamUartRx,pcUartRxBuf,sizeof(pcUartRxBuf));
    xStreamBufferStaticCreate(&xStreamUartTx,pcUartTxBuf,sizeof(pcUartTxBuf));
    xStreamBufferStaticCreate(&xStreamSlaverRx,pcSlaverRxBuf,sizeof(pcSlaverRxBuf));
    xStreamBufferStaticCreate(&xStreamSlaverTx,pcSlaverTxBuf,sizeof(pcSlaverTxBuf));
    xStreamBufferStaticCreate(&xStreamMasterRx,pcMasterRxBuf,sizeof(pcMasterRxBuf));
    xStreamBufferStaticCreate(&xStreamMasterTx,pcMasterTxBuf,sizeof(pcMasterTxBuf));
    uart_Cfg_t cfg = {
        .tx_pin = P20,
        .rx_pin = P18,
        .baudrate = 115200,
        .use_fifo = TRUE,
        .hw_fwctrl = FALSE,
        .use_tx_buf = TRUE,
        .parity     = FALSE,
        .evt_handler = uart_receive_callback,
    };
    HalUartInit(UART1, cfg);//uart init
    HalUartSetTxBuf(UART1, uart_send_buff, UART_SendBUF_SIZE);
    bleuart_AddService(ble_data_rec_evt);
}


uint16 Trasmit_ProcessEvent(uint8 task_id, uint16 events)
{
    uint8_t len = 0;
    uint8_t *pData = NULL;
    if (task_id != Trasmit_TaskID)
    {
        return 0;
    }
    if (events & SYS_EVENT_MSG)
    {
        osal_event_hdr_t *pMsg;

        if ((pMsg = (osal_event_hdr_t *)osal_msg_receive(Trasmit_TaskID)) != NULL)
        {
            LOG("sys_event_msg:UserAPP_TaskID=%d\r\n", Trasmit_TaskID);
            // Process incoming messages
            switch (pMsg->event)
            {
            // Incoming GATT message
            case GATT_MSG_EVENT:
                // gattServApp_ProcessMsg( (gattMsgEvent_t *)pMsg );
                break;

            default:
                // Unsupported message
                break;
            }
            ///< Release the OSAL message
            VOID osal_msg_deallocate((uint8 *)pMsg);
        }

        ///< return unprocessed events
        return (events ^ SYS_EVENT_MSG);
    }

    if( events & TrasmitEvent_UART_RCV)
    {
        // len = uartRxData.wr - uartRxData.rd;
        // LOG("RX-----len=%d\r\n",len);
        if(usStreamBufferNumberOfItemsGet(&xStreamUartRx))
        {
            len = usStreamBufferGetNextSize(&xStreamUartRx);
            if(len)
            {
                pData = osal_mem_alloc(len);
                if(pData)
                {
                    usStreamBufferRead(&xStreamUartRx,pData);
                    LOG("uart receve:");
                    for(uint8_t i = 0;i<len;i++)
                        // LOG("%02X ",uartRxData.data[(uartRxData.rd++)&UART_RX_BUF_INDEX]);
                        LOG("%02X ",pData[i]);
                    LOG("\r\n");
                    osal_mem_free(pData);
                }else{
                    LOG("Ram not ok\r\n");
                }
                // len = usStreamBufferGetNextSize(&xStreamUartRx);
                if(usStreamBufferNumberOfItemsGet(&xStreamUartRx))
                    Transmit_task_set(USER_TASK_START, TrasmitEvent_UART_RCV, 10);
                // else
                //     Transmit_task_set(USER_TASK_START, TrasmitEvent_UART_RCV, 64);
            }
        }
        // else{
        //     Transmit_task_set(USER_TASK_START, TrasmitEvent_UART_RCV, 64);
        // }
        return (events ^ TrasmitEvent_UART_RCV);
    }

    if( events & TrasmitEvent_UART_TX)
    {
        // LOG("TX-----len=%d\r\n",len);
        if(HalUartGetTxReady(UART1) == ERR_BUSY)
        {
            Transmit_task_set(USER_TASK_START, TrasmitEvent_UART_TX, 5);
        }else{
            // LOG("system t = %d need Send item=%d\r\n",osal_GetSystemClock(),usStreamBufferNumberOfItemsGet(&xStreamUartTx));
            if(usStreamBufferNumberOfItemsGet(&xStreamUartTx))
            {
                len = usStreamBufferGetNextSize(&xStreamUartTx);
                hal_pwrmgr_lock(MOD_GPIO);
                if(len <= UART_OneceBUF_SIZE)
                {
                    usStreamBufferRead(&xStreamUartTx,uart_send_buf);

                    LOG("uart send:");
                    my_dump_byte(uart_send_buf,len);
                    LOG("\r\n");

                    while(HalUartGetTxReady(UART1) == ERR_BUSY);
                    HalUartSendBuf(UART1, uart_send_buf, len);
                }else{
                    usStreamBufferRead(&xStreamUartTx,NULL);
                    LOG("send buffer is%d small than %d\r\n",UART_OneceBUF_SIZE,len);
                }
                if(usStreamBufferNumberOfItemsGet(&xStreamUartTx))
                    Transmit_task_set(USER_TASK_START, TrasmitEvent_UART_TX, 5);
            }else{
                hal_pwrmgr_unlock(MOD_GPIO);
                Transmit_task_set(USER_TASK_START, TrasmitEvent_UART_TX, 64);
            }
        }
        return (events ^ TrasmitEvent_UART_TX);
    }

    if( events & TrasmitEvent_Master_RCV)                   //Communication with rope
    {
        processMasterRcvData();
        return (events ^ TrasmitEvent_Master_RCV);
    }

    if( events & TrasmitEvent_Master_TX)                    //Communication with rope
    {
        // uint8_t pdulen = 0;                                 //注意考虑 pdu len
        attMsg_t sendMsg;
        // LOG("master TX-----len=%d\r\n",len);
        if(usStreamBufferNumberOfItemsGet(&xStreamMasterTx))
        {
            len = usStreamBufferGetNextSize(&xStreamMasterTx);
            pData = osal_mem_alloc(len);
            if(pData)
            {
                usStreamBufferRead(&xStreamMasterTx,pData);
                // LOG("tx 2 slaver ble:");
                // for(uint8_t i = 0;i<len;i++)
                //     LOG("%02X ",pData[i]);
                // LOG("\r\n");
                if(slaveDevInfo[0].ConnectionState)
                {
                    osal_memcpy(sendMsg.writeReq.value,pData,len);
                    sendMsg.writeReq.len = len;
                    user_data_send_by_ble(LL_ROLE_MASTER, 0, &sendMsg);
                }
                osal_mem_free(pData);
            }else{
                LOG("Ram not ok\r\n");
            }
            if(usStreamBufferNumberOfItemsGet(&xStreamMasterTx))
                Transmit_task_set(USER_TASK_START, TrasmitEvent_Master_TX, 10);
        }
        return (events ^ TrasmitEvent_Master_TX);
    }

    if( events & TrasmitEvent_Slaver_RCV)                   //Communication with app
    {
        if(usStreamBufferNumberOfItemsGet(&xStreamSlaverRx))
        {
            len = usStreamBufferGetNextSize(&xStreamSlaverRx);
            pData = osal_mem_alloc(len);
            if(pData)
            {
                usStreamBufferRead(&xStreamSlaverRx,pData);
                if(slaveDevInfo[0].ConnectionState)
                {
                    if(xBleCmdGet(pData,len) != CMD_ERROR)
                    {
                        xStreamBufferWrite(&xStreamMasterTx,pData,len);
                        Transmit_task_set(USER_TASK_START, TrasmitEvent_Master_TX, 10);
                    }
                }
                osal_mem_free(pData);
            }else{
                LOG("Ram not ok\r\n");
            }
            if(usStreamBufferNumberOfItemsGet(&xStreamSlaverRx))
                Transmit_task_set(USER_TASK_START, TrasmitEvent_Slaver_RCV, 10);
        }
        return (events ^ TrasmitEvent_Slaver_RCV);
    }

    if( events & TrasmitEvent_Slaver_TX)                    //Communication with app
    {
        // uint8_t pdulen = 0;                                 //注意考虑 pdu len
        attMsg_t sendMsg;
        // LOG("Slaver TX-----len=%d\r\n",len);
        if(usStreamBufferNumberOfItemsGet(&xStreamSlaverTx))
        {
            len = usStreamBufferGetNextSize(&xStreamSlaverTx);
            pData = osal_mem_alloc(len);
            if(pData)
            {
                usStreamBufferRead(&xStreamSlaverTx,pData);
                // LOG("tx 2 slaver ble:");
                // for(uint8_t i = 0;i<len;i++)
                //     LOG("%02X ",pData[i]);
                // LOG("\r\n");
                if(slaveDevInfo[0].ConnectionState)
                {
                    osal_memcpy(sendMsg.writeReq.value,pData,len);
                    sendMsg.writeReq.len = len;
                    user_data_send_by_ble(LL_ROLE_SLAVE, 0, &sendMsg);
                }
                osal_mem_free(pData);
            }else{
                LOG("Ram not ok\r\n");
            }
            if(usStreamBufferNumberOfItemsGet(&xStreamSlaverTx))
                Transmit_task_set(USER_TASK_START, TrasmitEvent_Slaver_TX, 30);
        }
        return (events ^ TrasmitEvent_Slaver_TX);
    }
    return 0;
}


static void processMasterRcvData(void)
{
    uint8_t len;
    uint8_t *pData = NULL;
    headSD_t *TempHSD = NULL; 
    tlv_t TempTlv; 
    if(usStreamBufferNumberOfItemsGet(&xStreamMasterRx))
    {
        len = usStreamBufferGetNextSize(&xStreamMasterRx);
        pData = osal_mem_alloc(len);
        if(pData)
        {
            usStreamBufferRead(&xStreamMasterRx,pData);
            // LOG("master receve:");
            // for(uint8_t i = 0;i<len;i++)
            //     LOG("%02X ",pData[i]);
            // LOG("\r\n");
            TempHSD = (headSD_t *)pData;
            if(TempHSD->head == TrasmitEvent_Head)
            {
                switch(TempHSD->destinationAddr)
                {
                    case    DeviceAddr_MulitPack:
                            {
                                TempTlv.type = *(pData+3);
                                TempTlv.len = *(pData+4);
                                TempTlv.data = (pData+5);
                                {
                                    switch(TempTlv.type)
                                    {
                                        case    DeviceCmd_Sleep:
                                                break;
                                        case    DeviceCmd_Status:
                                                TrageNotifyBleStatus();
                                                break;
                                        default:
                                                LOG("Unkown type = %02X\r\n",TempTlv.type);
                                                break;
                                    }
                                }
                            }
                            break;
                    case    DeviceAddr_LedDisplay:
                            {
                                if(xiaoBaiContorFlag.Flag.flagBit.EnableRemoteContor)
                                {
                                    xStreamBufferWrite(&xStreamUartTx,pData+3,len-3);
                                    Transmit_task_set(USER_TASK_START, TrasmitEvent_UART_TX, NULL);
                                }
                            }
                            break;
                    case    DeviceAddr_MulitCApp:
                            {
                                xStreamBufferWrite(&xStreamSlaverTx,pData+3,len-3);
                                Transmit_task_set(USER_TASK_START, TrasmitEvent_Slaver_TX, 10);
                            }
                            break;
                    default:
                            break;
                }
            }
            osal_mem_free(pData);
        }else{
            LOG("Ram not ok\r\n");
        }
        if(usStreamBufferNumberOfItemsGet(&xStreamMasterRx))
            Transmit_task_set(USER_TASK_START, TrasmitEvent_Master_RCV, 10);
    }
}

void NotifySlaverMasterStatus(void)
{
    uint8_t buffer[7];
    uint8_t index = 0;
    buffer[index++] = TrasmitEvent_Head;
    buffer[index++] = DeviceAddr_MulitPack;
    buffer[index++] = DeviceAddr_Rope;
    buffer[index++] = DeviceCmd_Status;
    buffer[index++] = 0x02;
    buffer[index++] = 0;
    buffer[index++] = masterDevInfo[0].ConnectionState;
    xStreamBufferWrite(&xStreamMasterTx,buffer,index);
}

/**
 * @fn      
 * @brief   BLE process
 * @param   
 * @return  
 */
HuaweiCmdDef xBleCmdGet(uint8* buf, uint8 len)
{
//	HuaweiCmdDef cmd;

	/* -----------------(1)----------------- */
	/* set time */
	if ((buf[0] == 1) && (buf[1] == 0) ){
		if (len != 6){
			return CMD_ERROR;
		}
		return CMD_SET_TIME;
	}

	/* -----------------(2)----------------- */
	/* read battery capacity */
	if ((buf[0] == 2) && (buf[1] == 0)){
		if (len != 2) {
			return CMD_ERROR;
		}
		return CMD_READ_BATCAP;
	}

	/* -----------------(3)----------------- */
	/* startup mode free jump */
	if ((buf[0] == 3) && (buf[1] == 1)) {
		if (len != 4) {
			return CMD_ERROR;
		}
		return CMD_START_FJ;
	}

	/* startup mode diminishing time */
	if ((buf[0] == 3) && (buf[1] == 2)) {
		if (len != 4) {
			return CMD_ERROR;
		}
		return CMD_START_DT;
	}

	/* startup mode diminishing counter */
	if ((buf[0] == 3) && (buf[1] == 3)) {
		if (len != 4) {
			return CMD_ERROR;
		}
		return CMD_START_DC;
	}

	/* mode suspend */
	if ((buf[0] == 3) && (buf[1] == 4)) {
		if (len != 4) {
			return CMD_ERROR;
		}
		return CMD_MD_SUSPEND;
	}

	/* mode recovery */
	if ((buf[0] == 3) && (buf[1] == 5)) {
		if (len != 4) {
			return CMD_ERROR;
		}
		return CMD_MD_RECOVERY;
	}

	/* mode stop */
	if ((buf[0] == 3) && (buf[1] == 6)) {
		if (len != 4) {
			return CMD_ERROR;
		}
		return CMD_MD_STOP;
	}

	/* start synchronization history record */
	if ((buf[0] == 3) && (buf[1] == 7)) {
		if (len != 4) {
			return CMD_ERROR;
		}
		return CMD_SYN_HISTORY;
	}

	/* End synchronization & delete history record */
	if ((buf[0] == 3) && (buf[1] == 8)) {
		if (len != 4) {
			return CMD_ERROR;
		}
		return CMD_SYN_END;
	}

	/* -----------------(4)----------------- */
	/* read device information */
	if ((buf[0] == 4) && (buf[1] == 0)) {
		if (len != 2) {
			return CMD_ERROR;
		}
		return CMD_READ_INFO;
	}

	return CMD_ERROR;
}


/**
 * @fn		void peripheral_task_set(uint8 action, uint16 event, uint32 time)
 * @brief
 * @param	none
 * @return	none
 */
void Transmit_task_set(uint8 action, uint16 event, uint32 time)
{
    osal_stop_timerEx(Trasmit_TaskID, event);
    if (action == USER_TASK_START)
    {
        if (time)
        {
            osal_start_timerEx(Trasmit_TaskID, event, time);
        }
        else
        {
            osal_set_event(Trasmit_TaskID, event);
        }
    }
}



